package cn.com.cloudpioneer.evaluate.service;

import com.jcraft.jsch.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;

/***********************************************************
 * @态度： 不因现实复杂而放弃梦想，不因理想遥远而放弃追求！
 * @追求： 白日依山尽，黄河入海流。欲穷千里目，更上一层楼！
 * @学习: 梦想从学习开始，事业从实践起步!
 * @作者： PAN Gaoming QQ: 1259484931 E-MAIL: mozicn@163.com
 * @作者主页： https://www.aicjh.com/  欢迎访问.
 * @日期： 2023/7/27  下午5:40
 * @详细描述:
 ************************************************************/
public class SSHClientService {
    private static final Logger LOGGER = LoggerFactory.getLogger(SSHClientService.class);
    private static volatile SSHClientService client;
    private String host;
    private int port;
    private String user;
    private String pass;

    private SSHClientService(String host, int port, String user, String pass) {
        this.host = host;
        this.port = port;
        this.user = user;
        this.pass = pass;
    }

    protected Session openSession() {
        Session session = null;
        try {
            session = new JSch().getSession(this.user, this.host, this.port);
        } catch (JSchException e) {
            e.printStackTrace();
            return null;
        }
        session.setPassword(pass);
        session.setConfig("StrictHostKeyChecking", "no");
        try {
            session.connect();
            return session;
        } catch (JSchException e) {
            e.printStackTrace();
            return null;
        }
    }

    protected void closeSession(Session session) {
        session.disconnect();
    }


    public static SSHClientService getSSHClient(String host, int port, String user, String pass) {
        if (client != null) {
            return client;
        }
        client = new SSHClientService(host, port, user, pass);
        return client;
    }

    public String doCommand(String cmdShell, boolean isPing) {
        Session session = this.openSession();
        if (session == null) {
            LOGGER.error("open session Err!!!!");
            return "Err";
        }
        ChannelShell channel = null;
        try {
            channel = (ChannelShell) session.openChannel("shell");
        } catch (JSchException e) {
            e.printStackTrace();
            this.closeSession(session);
            return "Err";
        }
        channel.setPty(true);
        OutputStream out = null;
        try {
            out = channel.getOutputStream();
        } catch (IOException e) {
            e.printStackTrace();
            this.closeSession(session);
            return "Err";
        }
        BufferedReader in = null;
        try {
            in = new BufferedReader(new InputStreamReader(channel.getInputStream()));
        } catch (IOException e) {
            e.printStackTrace();
            this.closeSession(session);
            return "Err";
        }
        try {
            channel.connect();
        } catch (JSchException e) {
            e.printStackTrace();
            this.closeSession(session);
            return "Err";
        }
        try {
            out.write(cmdShell.getBytes());
            out.flush();
        } catch (IOException e) {
            e.printStackTrace();
            channel.disconnect();
            this.closeSession(session);
            return "Err";
        }
        StringBuilder sb = new StringBuilder();
        char[] ch = new char[1024];
        int count = 0;
        int zeroCount = 0;
        do {
            try {
                if (in.ready()) {
                    count = in.read(ch, 0, 1024);
                } else {
                    zeroCount++;
                    Thread.sleep(2000L);
                }
            } catch (IOException | InterruptedException e) {
                e.printStackTrace();
            }
            if (count == 0) {
                zeroCount++;
            }
            if (count > 0) {
                for (int i = 0; i < count; i++)
                    sb.append(ch[i]);
            }
        } while (zeroCount < 5 && count != -1);
        try {
            out.close();
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        channel.disconnect();
        this.closeSession(session);
        return sb.toString();
    }

    public byte[] downloadByteArrayFile(String path, String fileName) {
        Session session = this.openSession();
        if (session == null) {
            LOGGER.error("open session Err!!!!");
            return null;
        }
        ChannelSftp sftpChannel = null;
        try {
            sftpChannel = (ChannelSftp) session.openChannel("sftp");
        } catch (JSchException e) {
            e.printStackTrace();
            this.closeSession(session);
            return null;
        }
        try {
            sftpChannel.connect();
        } catch (JSchException e) {
            e.printStackTrace();
            this.closeSession(session);
            return null;
        }
        try {
            sftpChannel.cd(path);
        } catch (SftpException e) {
            e.printStackTrace();
            this.closeSession(session);
            return null;
        }
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        try {
            sftpChannel.get(fileName, outputStream);
        } catch (SftpException e) {
            e.printStackTrace();
            this.closeSession(session);
            return null;
        }
        sftpChannel.exit();
        session.disconnect();
        this.closeSession(session);
        return outputStream.toByteArray();
    }
}
